﻿using MauiControl.Models;
using MauiControl.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Storage.Streams;

namespace MauiControl.Platforms.Windows.Services
{
    public class BluetoothServiceWindows : IBluetoothService, IDisposable
    {
        // 定义服务和特征码
        public static class Uuids
        {
            public const string Service = "0000ae30-0000-1000-8000-00805f9b34fb";
            public const string Write = "0000ae01-0000-1000-8000-00805f9b34fb";
            public const string Notify = "0000ae02-0000-1000-8000-00805f9b34fb";

            public const string GenericAccess = "00001800-0000-1000-8000-00805f9b34fb";
            public const string DeviceName = "00002a00-0000-1000-8000-00805f9b34fb";
            public const string BatteryService = "0000180f-0000-1000-8000-00805f9b34fb"; // 电池服务 UUID
            public const string BatteryLevel = "00002a19-0000-1000-8000-00805f9b34fb"; // 电池电量特征 UUID
        }

        private BluetoothLEAdvertisementWatcher _deviceWatcher;
        private List<BleDeviceInfo> _devices;
        private TaskCompletionSource<List<BleDeviceInfo>> _searchCompletionSource;
        private Action<BleDeviceInfo> _onDeviceAddedCallback;
        private readonly Dictionary<string, string> _discoveredDevices = new(); // 使用字符串作为键

        private BluetoothLEDevice _bluetoothLeDevice;
        private GattCharacteristic _receiveCharacteristic;
        private GattCharacteristic _sendCharacteristic;
        private bool _isConnected = false;
        private object _lockObject = new object();
        private bool _disposed = false;
        public event EventHandler<byte[]> DataReceived;

        public BluetoothServiceWindows()
        {
            _devices = new List<BleDeviceInfo>();
        }

        public async Task<List<BleDeviceInfo>> SearchDevicesAsync(CancellationToken cancellationToken, Action<BleDeviceInfo> onDeviceAddedCallback)
        {
            _devices.Clear();
            _discoveredDevices.Clear();

            _searchCompletionSource = new TaskCompletionSource<List<BleDeviceInfo>>();
            _onDeviceAddedCallback = onDeviceAddedCallback;

            if (_deviceWatcher != null && _deviceWatcher.Status == BluetoothLEAdvertisementWatcherStatus.Started)
            {
                _deviceWatcher.Stop();
            }

            _deviceWatcher = new BluetoothLEAdvertisementWatcher
            {
                ScanningMode = BluetoothLEScanningMode.Active
            };

            _deviceWatcher.Received += OnAdvertisementReceived;
            _deviceWatcher.Start();

            cancellationToken.Register(() =>
            {
                _deviceWatcher.Stop();
                _searchCompletionSource.TrySetCanceled();
            });

            try
            {
                await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
                _deviceWatcher.Stop();
                return _devices;
            }
            catch (TaskCanceledException)
            {
                _deviceWatcher.Stop();
                throw new OperationCanceledException("设备搜索已取消。");
            }
            catch (Exception ex)
            {
                _deviceWatcher.Stop();
                throw new Exception($"设备搜索失败: {ex.Message}");
            }
        }

        private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
        {
            var deviceName = string.IsNullOrEmpty(args.Advertisement.LocalName) ? "未知设备" : args.Advertisement.LocalName;
            var deviceAddress = args.BluetoothAddress.ToString("X12"); // 使用字符串形式的设备地址
            var formattedMacAddress = string.Join(":", Enumerable.Range(0, 6)
                .Select(i => deviceAddress.Substring(i * 2, 2)));

            var device = new BleDeviceInfo(
                name: deviceName,
                address: deviceAddress, // 使用 MAC 地址作为设备地址
                macAddress: formattedMacAddress, // 使用格式化后的 MAC 地址
                platformSpecificId: deviceAddress // 使用 MAC 地址作为平台特定标识符
            );

            if (!_discoveredDevices.ContainsKey(deviceAddress))
            {
                _discoveredDevices[deviceAddress] = deviceName;
                _devices.Add(device);
                _onDeviceAddedCallback?.Invoke(device);
            }
        }

        public async Task<BleDeviceInfo> ConnectDeviceAsync(string deviceId)
        {
            int retryCount = 6;
            for (int i = 0; i < retryCount; i++)
            {
                try
                {
                    Debug.WriteLine($"尝试连接设备，设备ID: {deviceId} (尝试次数: {i + 1})");

                    if (!_discoveredDevices.ContainsKey(deviceId))
                    {
                        throw new KeyNotFoundException($"未找到地址为 {deviceId} 的设备。");
                    }

                    var deviceName = _discoveredDevices[deviceId];
                    Debug.WriteLine($"设备名称: {deviceName}");

                    if (_bluetoothLeDevice != null && _bluetoothLeDevice.ConnectionStatus == BluetoothConnectionStatus.Connected)
                    {
                        Disconnect();
                    }

                    // 将字符串形式的设备地址转换为 ulong
                    if (!ulong.TryParse(deviceId, System.Globalization.NumberStyles.HexNumber, null, out ulong bluetoothAddress))
                    {
                        throw new Exception($"无法将设备ID {deviceId} 转换为 ulong。");
                    }

                    _bluetoothLeDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(bluetoothAddress);
                    Debug.WriteLine($"蓝牙对象: {_bluetoothLeDevice}");

                    if (_bluetoothLeDevice == null)
                    {
                        Debug.WriteLine("连接设备失败：无法获取设备对象。");
                        throw new Exception("连接设备失败：无法获取设备对象。");
                    }

                    _bluetoothLeDevice.ConnectionStatusChanged += OnConnectionStatusChangedHandler;
                    await Task.Delay(2000);

                    Debug.WriteLine($"设备连接状态: {_bluetoothLeDevice.ConnectionStatus}");

                    // 发现服务和特征
                    await DiscoverServicesAndCharacteristicsAsync();

                    // 启用通知
                    await EnableNotificationAsync();

                    // 读取电量信息
                    string batteryLevel = await GetBatteryLevelAsync(deviceId);

                    return new BleDeviceInfo(deviceName, deviceId, $"0x{deviceId}", deviceId)
                    {
                        BatteryLevel = batteryLevel // 更新电量信息
                    };
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"连接设备时出错: {ex.Message}");
                    if (i == retryCount - 1)
                    {
                        throw;
                    }
                    await Task.Delay(1000);
                }
            }

            throw new Exception("多次尝试后仍无法连接设备。");
        }

        private async Task DiscoverServicesAndCharacteristicsAsync()
        {
            var servicesResult = await _bluetoothLeDevice.GetGattServicesForUuidAsync(Guid.Parse(Uuids.Service));
            if (servicesResult.Status != GattCommunicationStatus.Success)
            {
                Debug.WriteLine("获取GATT服务失败。");
                throw new Exception("获取GATT服务失败。");
            }

            var targetService = servicesResult.Services.FirstOrDefault(s => s.Uuid == Guid.Parse(Uuids.Service));
            if (targetService == null)
            {
                Debug.WriteLine("未找到目标服务。");
                throw new Exception("未找到目标服务。");
            }

            var characteristicsResult = await targetService.GetCharacteristicsAsync();
            if (characteristicsResult.Status != GattCommunicationStatus.Success)
            {
                Debug.WriteLine("获取特征失败。");
                throw new Exception("获取特征失败。");
            }

            // 查找写入特征 (ae01)
            _sendCharacteristic = characteristicsResult.Characteristics.FirstOrDefault(c => c.Uuid == Guid.Parse(Uuids.Write));
            if (_sendCharacteristic == null)
            {
                Debug.WriteLine("未找到写入特征 (ae01)。");
                throw new Exception("未找到写入特征 (ae01)。");
            }

            // 查找接收特征 (ae02)
            _receiveCharacteristic = characteristicsResult.Characteristics.FirstOrDefault(c => c.Uuid == Guid.Parse(Uuids.Notify));
            if (_receiveCharacteristic == null)
            {
                Debug.WriteLine("未找到接收特征 (ae02)。");
                throw new Exception("未找到接收特征 (ae02)。");
            }

            // 打印特征值的 UUID 和属性
            Debug.WriteLine($"找到写入特征: {_sendCharacteristic.Uuid}, 属性: {_sendCharacteristic.CharacteristicProperties}");
            Debug.WriteLine($"找到接收特征: {_receiveCharacteristic.Uuid}, 属性: {_receiveCharacteristic.CharacteristicProperties}");
        }

        private async Task EnableNotificationAsync()
        {
            var notifyResult = await _receiveCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
                GattClientCharacteristicConfigurationDescriptorValue.Notify);
            if (notifyResult != GattCommunicationStatus.Success)
            {
                Debug.WriteLine("启用 Notify 失败。");
                throw new Exception("启用 Notify 失败。");
            }

            _receiveCharacteristic.ValueChanged += Characteristic_ValueChanged;
        }

        public async Task<byte[]> ReadRawDataAsync()
        {
            try
            {
                // 检查对象是否已被释放
                if (_disposed || _receiveCharacteristic == null)
                {
                    throw new InvalidOperationException("对象已释放或特征未初始化。");
                }

                var readResult = await _receiveCharacteristic.ReadValueAsync();
                if (readResult.Status == GattCommunicationStatus.Success)
                {
                    var reader = DataReader.FromBuffer(readResult.Value);
                    byte[] data = new byte[reader.UnconsumedBufferLength];
                    reader.ReadBytes(data);

                    Debug.WriteLine($"读取到的原始数据: {BitConverter.ToString(data)}");
                    return data;
                }
                else
                {
                    throw new Exception("读取数据失败。");
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"读取原始数据时出错: {ex.Message}");
                throw;
            }
        }

        public async Task WriteDataAsync(byte[] data)
        {
            try
            {
                // 检查对象是否已被释放
                if (_disposed || _sendCharacteristic == null)
                {
                    throw new InvalidOperationException("对象已释放或特征未初始化。");
                }

                // 打印要写入的数据
                Debug.WriteLine($"准备写入的数据: {BitConverter.ToString(data)}");

                // 发送数据
                var writeResult = await _sendCharacteristic.WriteValueAsync(data.AsBuffer(), GattWriteOption.WriteWithoutResponse);
                if (writeResult != GattCommunicationStatus.Success)
                {
                    throw new Exception("写入数据失败。");
                }

                Debug.WriteLine($"数据写入成功，特征 UUID: {_sendCharacteristic.Uuid}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"写入数据时出错: {ex.Message}");
                throw;
            }
        }

        public void Disconnect()
        {
            lock (_lockObject)
            {
                if (!_isConnected || _disposed) return;
                _isConnected = false;
            }

            try
            {
                if (_receiveCharacteristic != null)
                {
                    _receiveCharacteristic.ValueChanged -= Characteristic_ValueChanged;
                    _receiveCharacteristic = null;
                }

                if (_bluetoothLeDevice != null)
                {
                    _bluetoothLeDevice.ConnectionStatusChanged -= OnConnectionStatusChangedHandler;
                    _bluetoothLeDevice.Dispose();
                    _bluetoothLeDevice = null;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"断开连接时出错: {ex.Message}");
            }
        }

        private void OnConnectionStatusChangedHandler(BluetoothLEDevice sender, object args)
        {
            Debug.WriteLine($"连接状态变化: {sender.ConnectionStatus}");
            if (sender.ConnectionStatus == BluetoothConnectionStatus.Connected)
            {
                Debug.WriteLine("设备已连接。");
            }
            else if (sender.ConnectionStatus == BluetoothConnectionStatus.Disconnected)
            {
                Debug.WriteLine("设备已断开连接。");
                Disconnect();
            }
        }

        private void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
        {
            try
            {
                if (_disposed || _receiveCharacteristic == null)
                {
                    Debug.WriteLine("对象已释放，无法处理特征值变化。");
                    return;
                }

                // 读取接收到的数据
                byte[] valueBytes = new byte[args.CharacteristicValue.Length];
                DataReader.FromBuffer(args.CharacteristicValue).ReadBytes(valueBytes);

                Debug.WriteLine($"接收到数据包: {BitConverter.ToString(valueBytes)}");

                // 触发 DataReceived 事件
                DataReceived?.Invoke(this, valueBytes);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"处理特征值变化时出错: {ex.Message}");
            }
        }

        public void Dispose()
        {
            lock (_lockObject)
            {
                if (_disposed) return;
                _disposed = true;

                if (_receiveCharacteristic != null)
                {
                    _receiveCharacteristic.ValueChanged -= Characteristic_ValueChanged;
                    _receiveCharacteristic = null;
                }

                if (_bluetoothLeDevice != null)
                {
                    _bluetoothLeDevice.ConnectionStatusChanged -= OnConnectionStatusChangedHandler;
                    _bluetoothLeDevice.Dispose();
                    _bluetoothLeDevice = null;
                }
            }
        }

        /// <summary>
        /// 获取电池电量
        /// </summary>
        /// <param name="deviceId"></param>
        /// <returns></returns>
        public async Task<string> GetBatteryLevelAsync(string deviceId)
        {
            try
            {
                Guid batteryServiceUuid = Guid.Parse(Uuids.BatteryService);
                Guid batteryLevelCharacteristicUuid = Guid.Parse(Uuids.BatteryLevel);

                Debug.WriteLine("开始获取电池服务...");

                // 获取电池服务
                var servicesResult = await _bluetoothLeDevice.GetGattServicesForUuidAsync(batteryServiceUuid);
                if (servicesResult.Status != GattCommunicationStatus.Success)
                {
                    Debug.WriteLine("获取电池服务失败。");
                    return "N/A";
                }

                var batteryService = servicesResult.Services.FirstOrDefault();
                if (batteryService == null)
                {
                    Debug.WriteLine("未找到电池服务。");
                    return "N/A";
                }

                Debug.WriteLine("电池服务已找到，开始获取电量特征...");

                // 获取电量特征
                var characteristicsResult = await batteryService.GetCharacteristicsForUuidAsync(batteryLevelCharacteristicUuid);
                if (characteristicsResult.Status != GattCommunicationStatus.Success)
                {
                    Debug.WriteLine("获取电量特征失败。");
                    return "N/A";
                }

                var batteryLevelCharacteristic = characteristicsResult.Characteristics.FirstOrDefault();
                if (batteryLevelCharacteristic == null)
                {
                    Debug.WriteLine("未找到电量特征。");
                    return "N/A";
                }

                Debug.WriteLine("电量特征已找到，开始读取电量值...");

                // 读取电量值
                var readResult = await batteryLevelCharacteristic.ReadValueAsync();
                if (readResult.Status == GattCommunicationStatus.Success)
                {
                    var reader = DataReader.FromBuffer(readResult.Value);
                    byte batteryLevel = reader.ReadByte();
                    Debug.WriteLine($"读取到的电量值: {batteryLevel}%");
                    return $"{batteryLevel}%";
                }
                else
                {
                    Debug.WriteLine("读取电量值失败。");
                    return "N/A";
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"读取电量信息时出错: {ex.Message}");
                return "N/A";
            }
        }
    }
}